module.exports = function(url,fn,args){
    var _$ = a;
    args = args || {};
    var _this = this;
    this.url = url;
    this.id = args.id || _$.zIndex();
    this.header = args.header || [];
    this.loading = args.loading || {};
    this.type = args.meth ? args.meth.toLowerCase() : 'GET';
    this.dataType = args.dataType || 'json';
    this.contentType = args.contentType || this.dataType == 'json' ? 'application/json' : 'application/x-www-form-urlencoded; charset=UTF-8';
    this.async = args.async === false ? false : true;
    this.data = args.data || {};
    this.progress = args.progress;
    this.cache = args.cache === false ? false : true;
    this.finalFn = fn;
    this.storage = args.storage || {};
    this.autoLogin = args.autoLogin || false;//拦截到登录失效时 是否自动登录
    if(args.storageName) this.storage.name = args.storageName;
    if(this.storage.name) _$.Storage.init(this.storage.name,this.storage);
    if(!_$.Storage.get('ajaxing')) _$.Storage.set('ajaxing',{});
    this.xhr = args.xhr || new XMLHttpRequest();
    if(_this.xhr.upload){
        _this.xhr.upload.onprogress = function (e) {
            if (e.lengthComputable && _this.progress) _this.progress(e);
        }
        _this.xhr.onload = function (e) {
            _this.complete(e);
        }
        _this.xhr.onabort = function (e) {
            if(_this.loading.close) _this.loading.close();
            _this.returnFn({errorMsg:_this.xhr.responseText ? _this.xhr.responseText : '请求中断'});
        }
        _this.xhr.onerror = function (e) {
            if(_this.loading.close) _this.loading.close();
            _this.returnFn({errorMsg:_this.xhr.responseText ? _this.xhr.responseText : '连接服务器失败'});
        }
    }else{
        _this.xhr.onreadystatechange = function(){
            if(_this.xhr.readyState == 4){
                _this.complete();
            }
        }
    }
    this.abort = function(){
        if(_this.xhr.onabort) _this.xhr.abort();
    }
    this.complete = function(res){
        if(_this.loading.close) _this.loading.close();
        if(_this.xhr.status == 404){
            this.returnFn({errorMsg:_this.xhr.statusText || '404'});
        }else{
            res = _this.xhr.responseText || res || '';
            if(this.dataType.toLowerCase() == 'json' && typeof res == 'string'){
                try{
                    let base64 = new _$.Base64()
                    if(base64.canDecode(res)) res = base64.decodeURI(res)
                    res = JSON.parse(res)
                }catch(e){
                    console.log(e)
                    res = {errorMsg:'返回数据格式错误'}
                }
            }
            var loginAction = _$.Storage.get('loginAction');
            if(loginAction && !args.noLoginAction) {
                loginAction.call(_this,res,function(res){
                    _this.returnFn('',res);
                })
            }else{
                _this.returnFn('',res);
            }
        }
    }
    this.actionKey = '';
    this.itemNext = '';
    this.returned = false;
    this.timeoutTimer = '';
    this.returnFn = function(err,res,storageReturn){
        if(this.timeoutTimer) {
            clearTimeout(this.timeoutTimer);
            this.timeoutTimer = '';
        }
        if(this.returned) return false;
        this.returned = true;
        if(err) {
            res = err;
            err.xhr = this.xhr;
        }
        if(!storageReturn && !res.errorMsg && this.storage.name){
            _$.Storage.set(this.storage.name,res);
        }
        this.finalFn(res,err,this.actionKey);
        if(this.itemNext) this.itemNext();
    }
    this.action = function(key,finalFn){
        try{
            this.returned = false;
            var beforeLoginAction = _$.Storage.get('beforeLoginAction');
            if(beforeLoginAction && !args.noBeforeLoginAction) beforeLoginAction.call(this);
            var url = _$.string(this.url)._eval(this.data).toString();
            this.actionKey = key;
            if(finalFn && typeof finalFn == 'function') this.finalFn = finalFn;
            var storageData = this.storage && this.storage.name && _$.Storage.get(this.storage.name);
            if(storageData){//从缓存获取
                this.returnFn('',storageData,true);
            }else{
                var dataString = '';
                if(this.data && this.data.constructor && (this.data.constructor.toString().indexOf('function FormData()') == 0 || this.data.constructor.toString().indexOf('function Blob()') == 0)){
                    dataString = this.data;
                    this.contentType = '';//文件上传去掉Content-Type
                }else{
                    if(this.cache && this.type.toUpperCase() == 'GET') this.data['_'] = (new Date()).getTime();
                    var theOne = true;
                    var data = _$.clone(this.data,true);
                    for(var k in data) {
                        if(data[k] === undefined) continue;
                        data[k] = encodeURI(typeof data[k] == 'object' ? JSON.stringify(data[k]) : data[k]);
                        if(theOne){
                            dataString += k + '=' + data[k];
                            theOne = false;
                        }else{
                            dataString += '&' + k + '=' + data[k];
                        }
                    }
                    if(args.urlQuery || this.type.toUpperCase() == 'GET' || this.type.toUpperCase() == 'DELETE'){
                        if(url.indexOf('?') == -1) url += '?';
                        url += (url.charAt(url.length - 1) == '?' ? '' : '&') + dataString;
                        dataString = '';
                    }
                    args.dataJson = args.dataJson == undefined ? true : args.dataJson;
                    if((this.type.toUpperCase() == 'POST' || this.type.toUpperCase() == 'PUT') && args.dataJson){
                        var dataEmpty = true;
                        for(var k in this.data) dataEmpty = false;
                        dataString = !dataEmpty ? JSON.stringify(this.data) : '';
                        this.contentType = 'application/json;charset=utf-8';
                    }
                }
                var item = '';
                if(args.Item == true){
                    item = _$.Storage.get('_ajaxItems');
                    if(!item){
                        item = new _$.Item({max:5});
                        _$.Storage.set('_ajaxItems',item);
                    }
                }else{
                    item = args.Item;
                }
                if(typeof item == 'object' && item.typeOf == 'Item'){
                    item._push(itemFn);
                }else{
                    itemFn();
                }
                function itemFn(next){
                    if(next) _this.itemNext = next;
                    if(_this.loading.open) _this.loading.open();
                    _this.xhr.open(_this.type, url,_this.async);
                    if(_this.contentType) _this.xhr.setRequestHeader('Content-Type', _this.contentType);
                    try{
                        if(args.unAjaxHeader !== true){
                            var ajaxHeader = _$.Storage.get('ajaxHeader');
                            for(i = 0; i < ajaxHeader.length; i++){
                                _this.xhr.setRequestHeader(ajaxHeader[i].key, ajaxHeader[i].value);
                            }
                        }
                    }catch(e){}
                    for(var i = 0; i < _this.header.length; i ++){
                        _this.xhr.setRequestHeader(_this.header[i].key, _this.header[i].value);
                    }
                    _this.xhr.send(dataString);
                    var timeout = args.timeout ? args.timeout : _$.Storage.get('ajaxTimeOut');
                    if(timeout > 0){
                        _this.timeoutTimer = setTimeout(function(){
                            if(_this.loading.close) _this.loading.close();
                            _this.returnFn({errorMsg:'请求超时'});
                        },timeout)
                    }
                }
            }
        }catch(e){
            console.log(e);
            _this.returnFn({errorMsg:'请求异常'});
        }
        
    }
    this.fetch = (url,args)=>{
        if(url) this.url = url
        if(args) {
            if(args.method) this.type = args.method
            if(args.body) this.data = args.body
            if(args.headers) for(let key in args.headers) this.header.push({key,value:args.headers[key]})
        }
        return new Promise(next => {
            this.action(null,(data)=>{
                next(data)
            })
        })
    }
}